package com.ecommerce.payment.service.impl;

import com.ecommerce.common.core.ApiResult;
import com.ecommerce.common.exception.BusinessException;
import com.ecommerce.order.dto.OrderInfo;
import com.ecommerce.order.entity.OrderStatus;
import com.ecommerce.payment.client.AlipayClient;
import com.ecommerce.payment.client.WechatPayClient;
import com.ecommerce.payment.dto.*;
import com.ecommerce.payment.entity.Payment;
import com.ecommerce.payment.entity.PaymentStatus;
import com.ecommerce.payment.event.PaymentSuccessEvent;
import com.ecommerce.payment.repository.PaymentRepository;
import com.ecommerce.payment.service.PaymentService;
import com.ecommerce.order.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Random;

/**
 * 支付服务实现类
 */
@Service
@Transactional
@Slf4j
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private PaymentRepository paymentRepository;

    @Autowired
    private OrderService orderService;

    @Autowired
    private AlipayClient alipayClient;

    @Autowired
    private WechatPayClient wechatPayClient;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public ApiResult<PaymentResponse> createPayment(CreatePaymentRequest request) {
        log.info("创建支付订单: orderNo={}, method={}", request.getOrderNo(), request.getMethod());

        try {
            // 1. 验证订单状态
            OrderInfo orderInfo = orderService.getOrderByNo(request.getOrderNo());
            if (orderInfo == null) {
                return ApiResult.badRequest("订单不存在");
            }

            if (orderInfo.getStatus() != OrderStatus.PENDING_PAYMENT) {
                return ApiResult.badRequest("订单状态不正确");
            }

            // 2. 检查是否已有支付记录
            Payment existingPayment = paymentRepository.findByOrderNoAndStatus(
                request.getOrderNo(), PaymentStatus.PENDING);

            if (existingPayment != null) {
                // 返回已存在的支付记录
                PaymentResponse response = PaymentResponse.fromPayment(existingPayment);
                return ApiResult.success(response);
            }

            // 3. 创建支付记录
            Payment payment = Payment.builder()
                    .paymentNo(generatePaymentNo())
                    .orderNo(request.getOrderNo())
                    .userId(orderInfo.getUserId())
                    .method(request.getMethod())
                    .status(PaymentStatus.PENDING)
                    .amount(orderInfo.getPayAmount())
                    .build();

            payment = paymentRepository.save(payment);

            // 4. 调用第三方支付接口
            ThirdPartyPaymentResult paymentResult = callThirdPartyPayment(payment, request);

            // 5. 更新支付记录
            payment.setThirdPartyPaymentNo(paymentResult.getThirdPartyPaymentNo());
            payment.setStatus(PaymentStatus.PROCESSING);
            paymentRepository.save(payment);

            log.info("支付订单创建成功: paymentNo={}", payment.getPaymentNo());

            PaymentResponse response = PaymentResponse.fromPayment(payment);
            response.setPaymentUrl(paymentResult.getPaymentUrl());
            response.setQrCode(paymentResult.getQrCode());

            return ApiResult.success("支付订单创建成功", response);

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("创建支付订单失败: orderNo={}, error={}", request.getOrderNo(), e.getMessage(), e);
            throw new BusinessException("创建支付订单失败，请稍后重试");
        }
    }

    @Override
    public ApiResult<PaymentResponse> queryPaymentStatus(String paymentNo) {
        log.info("查询支付状态: paymentNo={}", paymentNo);

        try {
            // 查找支付记录
            Payment payment = paymentRepository.findByPaymentNo(paymentNo)
                    .orElseThrow(() -> new BusinessException("支付记录不存在"));

            PaymentResponse response = PaymentResponse.fromPayment(payment);
            return ApiResult.success(response);
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("查询支付状态失败: paymentNo={}, error={}", paymentNo, e.getMessage(), e);
            throw new BusinessException("查询支付状态失败");
        }
    }

    @Override
    public ApiResult<PaymentResponse> handlePaymentCallback(PaymentCallbackRequest request) {
        log.info("处理支付回调: paymentNo={}, status={}", request.getPaymentNo(), request.getStatus());

        try {
            // 1. 验证回调签名
            if (!verifyCallbackSignature(request)) {
                log.warn("支付回调签名验证失败: paymentNo={}", request.getPaymentNo());
                return ApiResult.error("签名验证失败");
            }

            // 2. 查找支付记录
            Payment payment = paymentRepository.findByPaymentNo(request.getPaymentNo())
                    .orElseThrow(() -> new BusinessException("支付记录不存在"));

            // 3. 检查支付状态
            if (payment.getStatus() == PaymentStatus.SUCCESS) {
                log.info("支付已成功，忽略重复回调: paymentNo={}", request.getPaymentNo());
                return ApiResult.success();
            }

            // 4. 更新支付状态
            if ("SUCCESS".equals(request.getStatus())) {
                payment.setStatus(PaymentStatus.SUCCESS);
                payment.setPayTime(LocalDateTime.now());
                payment.setThirdPartyPaymentNo(request.getThirdPartyPaymentNo());

                // 5. 更新订单状态
                orderService.paymentSuccess(payment.getOrderNo(), payment.getPaymentNo());

                // 6. 发送支付成功事件
                publishPaymentSuccessEvent(payment);

                log.info("支付成功: paymentNo={}, orderNo={}", payment.getPaymentNo(), payment.getOrderNo());

            } else {
                payment.setStatus(PaymentStatus.FAILED);
                payment.setFailureReason(request.getFailureReason());

                log.info("支付失败: paymentNo={}, reason={}", payment.getPaymentNo(), request.getFailureReason());
            }

            paymentRepository.save(payment);

            return ApiResult.success();

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("处理支付回调失败: paymentNo={}, error={}", request.getPaymentNo(), e.getMessage(), e);
            throw new BusinessException("处理支付回调失败");
        }
    }

    @Override
    public ApiResult<RefundResponse> requestRefund(RefundRequest request) {
        log.info("申请退款: paymentNo={}, amount={}", request.getPaymentNo(), request.getRefundAmount());

        try {
            // 1. 查找支付记录
            Payment payment = paymentRepository.findByPaymentNo(request.getPaymentNo())
                    .orElseThrow(() -> new BusinessException("支付记录不存在"));

            // 2. 检查支付状态
            if (payment.getStatus() != PaymentStatus.SUCCESS) {
                return ApiResult.badRequest("只有支付成功的订单才能申请退款");
            }

            // 3. 检查退款金额
            BigDecimal paymentAmount = new BigDecimal(payment.getAmount()).divide(new BigDecimal(100));
            if (request.getRefundAmount().compareTo(paymentAmount) > 0) {
                return ApiResult.badRequest("退款金额不能大于支付金额");
            }

            // 4. 调用第三方退款接口（简化实现）
            boolean refundSuccess = callThirdPartyRefund(payment, request);

            if (!refundSuccess) {
                return ApiResult.error("退款申请失败");
            }

            // 5. 更新支付状态
            payment.setStatus(PaymentStatus.REFUNDED);
            paymentRepository.save(payment);

            // 6. 构造退款响应
            RefundResponse response = new RefundResponse();
            response.setRefundNo("REFUND" + System.currentTimeMillis());
            response.setPaymentNo(payment.getPaymentNo());
            response.setRefundAmount(request.getRefundAmount());
            response.setRefundStatus("SUCCESS");
            response.setRefundTime(LocalDateTime.now());
            response.setCreateTime(LocalDateTime.now());
            response.setUpdateTime(LocalDateTime.now());

            log.info("退款申请成功: refundNo={}", response.getRefundNo());
            return ApiResult.success("退款申请成功", response);
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("申请退款失败: paymentNo={}, error={}", request.getPaymentNo(), e.getMessage(), e);
            throw new BusinessException("申请退款失败");
        }
    }

    @Override
    public ApiResult<RefundResponse> queryRefundStatus(String refundNo) {
        log.info("查询退款状态: refundNo={}", refundNo);

        // 简化实现，实际应该查询第三方支付系统的退款状态
        RefundResponse response = new RefundResponse();
        response.setRefundNo(refundNo);
        response.setRefundStatus("SUCCESS");
        response.setRefundTime(LocalDateTime.now());
        
        return ApiResult.success(response);
    }

    /**
     * 调用第三方支付接口
     */
    private ThirdPartyPaymentResult callThirdPartyPayment(Payment payment, CreatePaymentRequest request) {
        switch (payment.getMethod()) {
            case ALIPAY:
                return alipayClient.createPayment(payment, request);
            case WECHAT:
                return wechatPayClient.createPayment(payment, request);
            case BANK_CARD:
                // 银行卡支付逻辑
                throw new BusinessException("暂不支持银行卡支付");
            default:
                throw new BusinessException("不支持的支付方式");
        }
    }

    /**
     * 调用第三方退款接口
     */
    private boolean callThirdPartyRefund(Payment payment, RefundRequest request) {
        // 简化实现，实际应该调用第三方支付系统的退款接口
        // 这里模拟第三方退款成功
        return true;
    }

    /**
     * 验证回调签名
     */
    private boolean verifyCallbackSignature(PaymentCallbackRequest request) {
        // 简化实现，实际应该根据不同支付方式验证签名
        return true;
    }

    /**
     * 生成支付单号
     */
    private String generatePaymentNo() {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String random = String.format("%04d", new Random().nextInt(10000));
        return "PAY" + timestamp + random;
    }

    /**
     * 发布支付成功事件
     */
    private void publishPaymentSuccessEvent(Payment payment) {
        try {
            PaymentSuccessEvent event = new PaymentSuccessEvent(
                payment.getPaymentNo(),
                payment.getOrderNo(),
                payment.getUserId(),
                payment.getAmount(),
                payment.getPayTime()
            );
            rabbitTemplate.convertAndSend("payment.exchange", "payment.success", event);
        } catch (Exception e) {
            log.warn("发送支付成功事件失败: paymentNo={}, error={}", payment.getPaymentNo(), e.getMessage());
        }
    }
}